package main

import (
	"fmt"
	"unsafe"
)

/*
位运算
*/
func main() {
	//jiaohuan()
	//fappend()
	//pase_student()
	countmap2()
}

/**
位运算的用途之一
交换两个变量的值
不通过第三个变量
*/
func jiaohuan() {
	a := 12
	b := 24

	a = a ^ b
	b = a ^ b
	a = a ^ b
	fmt.Println(a)
	fmt.Println(b)
}

/**
结构体切片拷贝
*/
func f(a int, b uint) {

	val := copy(make([]struct{}, a), make([]struct{}, b))
	fmt.Printf("%d\n", val)
	/*
	   解析：
	   copy返回的是拷贝成功的个数，在第一个结构体切片空间用完或者，第二个结构体切片完全复制后会停止，
	   较小的数字则为实际copy的个数
	*/
}

//自定义类型
type Hash [32]byte

func MustNotBeZero(h Hash) {
	/**
	解析：
	首先h是一个形参变量
	Hash是一个数据类型。
	变量不能和数据类型做比较
	*/
	//if h == Hash {
	//	fmt.Println(1)

	//阔以修改为如下
	//注意不能写成 [32]byte ,这样写他也表示是数据类型
	if h == [32]byte{} {

	}
}

/**

 */
func fappend() {
	v := []int{1, 2, 3}
	for i, _ := range v {
		v = append(v, i)
		//fmt.Println(unsafe.Pointer(&v))
	}
	//答案：1,2,3,0,1,2
	fmt.Println(v)
	/**
		他居然没有报错？
		原因：
	    range在运行时候会对数据源进行一次拷贝，所以不会影响到数据的输出
	*/
}

/**
切片截取
*/
func qiepianjiequ() {
	a := []int{0, 1, 2, 3, 4, 5, 6, 7}
	b := a[:3]
	//b的输出为：[0,1,2]
	b = append(b, 4)
	//b的输出为：[0,1,2,4]
	fmt.Println(a)
	fmt.Println(b)
}

type student struct {
	Name string
	Age  int
}

func pase_student() {
	m := make(map[string]*student)
	stus := []student{
		{Name: "zhow", Age: 24},
		{Name: "li", Age: 23},
		{Name: "wang", Age: 22},
	}

	for _, stu := range stus {
		fmt.Println(unsafe.Pointer(&stu))
		m[stu.Name] = &stu
	}

	/*
			解析：
			首先打印出来的map结果是无序的，
			然后如果是通过for range循环，他将会执行同一个内存地址
		    并不是我们想要的结果，如果想查看每个切片元素的内存地址
		    需要通过 for i 这种循环
	*/

	//for i := 0; i < len(stus); i++ {
	//	m[stus[i].Name] = &stus[i]
	//}

	fmt.Println(m)
}

/**
巧用map实现数据统计
*/
func countmap() {
	m := make(map[string]int)
	m["foo"]++
	/*
			解析：
			首先答案是 1
			原因：当key "foo" 在m字典中未查找到数据的时候
			他会创建这个 "foo" 作为key, value就是在定义 map
			的时候的 value对应类型的 零值
		    所以，这儿的 零值 就是 0
		    0++  就是 1
	*/
	fmt.Println(m)
}

/**
巧用map统计一段字符串中
各个字符出现的次数
*/
func countmap2() {
	str := "andjfkasndfkasnmdfdk"
	m := make(map[byte]int)

	for i := 0; i < len(str); i++ {
		m[str[i]]++
	}

	for k, v := range m {
		fmt.Printf("字符%c,出现了:%d次\n", k, v)
	}
}
